# -*- coding: utf-8 -*-
"""
数据清理服务

按照模块文档2.3.3节要求实现数据清理功能：
- 过期数据自动清理
- 清理规则配置管理
- 清理记录和统计
"""

import json
from typing import Dict, List, Optional, Any
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from sqlalchemy import text, and_
import logging

from ..core.database import get_db
from ..core.exceptions import BusinessError, ValidationError
from ..models.system_config import SystemConfig
from ..models.rbac import PermissionLog, User, UserStatus

logger = logging.getLogger(__name__)


class CleanupService:
    """数据清理服务类"""

    def __init__(self, db: Session):
        self.db = db

    async def configure_cleanup_rules(
        self, 
        rules: Dict[str, Any], 
        operator: str
    ) -> Dict[str, Any]:
        """
        配置清理规则
        
        Args:
            rules: 清理规则配置
            operator: 操作人
            
        Returns:
            配置结果
        """
        try:
            # 验证清理规则
            validated_rules = self._validate_cleanup_rules(rules)
            
            # 保存清理规则到系统配置
            for rule_key, rule_config in validated_rules.items():
                config_key = f"cleanup.{rule_key}"
                config_value = json.dumps(rule_config, ensure_ascii=False)
                
                # 查找或创建配置项
                config = self.db.query(SystemConfig).filter(
                    SystemConfig.config_key == config_key
                ).first()
                
                if config:
                    config.config_value = config_value
                    config.updated_by = operator
                else:
                    config = SystemConfig(
                        config_key=config_key,
                        config_value=config_value,
                        config_category="system",
                        config_type="json",
                        display_name=f"数据清理规则-{rule_key}",
                        description=f"{rule_key}类型数据的清理规则",
                        group_name="数据清理",
                        created_by=operator,
                        updated_by=operator
                    )
                    self.db.add(config)
            
            self.db.commit()
            
            logger.info(f"清理规则配置成功, 操作人: {operator}")
            return {
                "success": True,
                "message": "清理规则配置成功",
                "rules_count": len(validated_rules)
            }
            
        except Exception as e:
            self.db.rollback()
            logger.error(f"配置清理规则失败: {e}", exc_info=True)
            raise BusinessError(f"配置清理规则失败: {str(e)}")

    def get_cleanup_config(self) -> Dict[str, Any]:
        """获取当前清理配置"""
        try:
            # 从系统配置加载清理规则
            configs = self.db.query(SystemConfig).filter(
                SystemConfig.config_key.like("cleanup.%")
            ).all()
            
            cleanup_rules = {}
            for config in configs:
                rule_key = config.config_key.replace("cleanup.", "")
                try:
                    rule_config = json.loads(config.config_value)
                    cleanup_rules[rule_key] = rule_config
                except json.JSONDecodeError:
                    logger.warning(f"清理规则配置格式错误: {config.config_key}")
            
            # 如果没有配置，返回默认规则
            if not cleanup_rules:
                cleanup_rules = self._get_default_cleanup_rules()
            
            return {
                "rules": cleanup_rules,
                "last_updated": datetime.now().isoformat()
            }
            
        except Exception as e:
            logger.error(f"获取清理配置失败: {e}")
            raise BusinessError(f"获取清理配置失败: {str(e)}")

    async def execute_cleanup(
        self, 
        cleanup_types: Optional[List[str]] = None,
        dry_run: bool = False,
        operator: str = "system"
    ) -> Dict[str, Any]:
        """
        执行数据清理
        
        Args:
            cleanup_types: 指定清理类型，None表示全部
            dry_run: 是否为试运行（不实际删除）
            operator: 操作人
            
        Returns:
            清理结果统计
        """
        try:
            cleanup_config = self.get_cleanup_config()
            cleanup_rules = cleanup_config["rules"]
            
            # 筛选要清理的类型
            if cleanup_types:
                cleanup_rules = {
                    k: v for k, v in cleanup_rules.items() 
                    if k in cleanup_types
                }
            
            cleanup_results = {}
            total_deleted = 0
            
            # 创建清理记录
            cleanup_id = self._generate_cleanup_id()
            cleanup_record = {
                "cleanup_id": cleanup_id,
                "started_at": datetime.now().isoformat(),
                "dry_run": dry_run,
                "operator": operator,
                "types": list(cleanup_rules.keys()),
                "status": "in_progress"
            }
            
            # 逐个执行清理任务
            for data_type, rule_config in cleanup_rules.items():
                if not rule_config.get("enabled", True):
                    continue
                
                try:
                    result = await self._cleanup_data_type(data_type, rule_config, dry_run)
                    cleanup_results[data_type] = result
                    total_deleted += result.get("deleted_count", 0)
                    
                except Exception as e:
                    logger.error(f"清理{data_type}数据失败: {e}")
                    cleanup_results[data_type] = {
                        "success": False,
                        "error": str(e),
                        "deleted_count": 0
                    }
            
            # 更新清理记录
            cleanup_record.update({
                "completed_at": datetime.now().isoformat(),
                "status": "completed",
                "results": cleanup_results,
                "total_deleted": total_deleted
            })
            
            # 保存清理记录
            await self._save_cleanup_record(cleanup_record)
            
            if not dry_run:
                self.db.commit()
            
            logger.info(f"数据清理完成: {cleanup_id}, 清理{total_deleted}条记录")
            return cleanup_record
            
        except Exception as e:
            if not dry_run:
                self.db.rollback()
            logger.error(f"执行数据清理失败: {e}", exc_info=True)
            raise BusinessError(f"执行数据清理失败: {str(e)}")

    def get_cleanup_history(
        self, 
        page: int = 1, 
        size: int = 20,
        cleanup_type: Optional[str] = None
    ) -> Dict[str, Any]:
        """获取清理历史记录"""
        try:
            cleanup_records = self._load_cleanup_records()
            
            # 筛选清理类型
            if cleanup_type:
                cleanup_records = [
                    record for record in cleanup_records
                    if cleanup_type in record.get("types", [])
                ]
            
            # 分页
            total = len(cleanup_records)
            start = (page - 1) * size
            end = start + size
            page_records = cleanup_records[start:end]
            
            return {
                "items": page_records,
                "total": total,
                "page": page,
                "size": size
            }
            
        except Exception as e:
            logger.error(f"获取清理历史失败: {e}")
            raise BusinessError(f"获取清理历史失败: {str(e)}")

    async def _cleanup_data_type(
        self, 
        data_type: str, 
        rule_config: Dict[str, Any], 
        dry_run: bool
    ) -> Dict[str, Any]:
        """清理指定类型的数据"""
        try:
            retention_days = rule_config.get("retention_days", 30)
            cutoff_date = datetime.now() - timedelta(days=retention_days)
            
            if data_type == "operation_logs":
                return await self._cleanup_operation_logs(cutoff_date, dry_run)
            elif data_type == "login_records":
                return await self._cleanup_login_records(cutoff_date, dry_run)
            elif data_type == "deleted_users":
                return await self._cleanup_deleted_users(cutoff_date, dry_run)
            elif data_type == "temp_files":
                return await self._cleanup_temp_files(cutoff_date, dry_run)
            elif data_type == "error_logs":
                return await self._cleanup_error_logs(cutoff_date, dry_run)
            else:
                logger.warning(f"未知的清理数据类型: {data_type}")
                return {
                    "success": False,
                    "error": f"未知的数据类型: {data_type}",
                    "deleted_count": 0
                }
                
        except Exception as e:
            logger.error(f"清理{data_type}数据失败: {e}")
            return {
                "success": False,
                "error": str(e),
                "deleted_count": 0
            }

    async def _cleanup_operation_logs(self, cutoff_date: datetime, dry_run: bool) -> Dict[str, Any]:
        """清理操作日志"""
        try:
            # 查询需要清理的记录
            query = self.db.query(PermissionLog).filter(
                PermissionLog.operated_at < cutoff_date
            )
            
            count = query.count()
            
            if not dry_run and count > 0:
                query.delete(synchronize_session=False)
            
            return {
                "success": True,
                "deleted_count": count,
                "cutoff_date": cutoff_date.isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "deleted_count": 0
            }

    async def _cleanup_login_records(self, cutoff_date: datetime, dry_run: bool) -> Dict[str, Any]:
        """清理登录记录"""
        try:
            # TODO: 如果有专门的登录记录表，在这里清理
            # 目前用户表中的last_login_at字段不需要清理
            return {
                "success": True,
                "deleted_count": 0,
                "message": "登录记录存储在用户表中，不需要清理"
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "deleted_count": 0
            }

    async def _cleanup_deleted_users(self, cutoff_date: datetime, dry_run: bool) -> Dict[str, Any]:
        """清理已删除用户"""
        try:
            # 查询需要清理的已删除用户
            query = self.db.query(User).filter(
                and_(
                    User.status == UserStatus.DELETED,
                    User.updated_at < cutoff_date
                )
            )
            
            count = query.count()
            
            if not dry_run and count > 0:
                # 硬删除已标记删除的用户
                query.delete(synchronize_session=False)
            
            return {
                "success": True,
                "deleted_count": count,
                "cutoff_date": cutoff_date.isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "deleted_count": 0
            }

    async def _cleanup_temp_files(self, cutoff_date: datetime, dry_run: bool) -> Dict[str, Any]:
        """清理临时文件"""
        try:
            # TODO: 实现临时文件清理逻辑
            # 需要根据实际的文件存储方式实现
            return {
                "success": True,
                "deleted_count": 0,
                "message": "临时文件清理功能待实现"
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "deleted_count": 0
            }

    async def _cleanup_error_logs(self, cutoff_date: datetime, dry_run: bool) -> Dict[str, Any]:
        """清理错误日志"""
        try:
            # TODO: 实现错误日志清理逻辑
            # 需要根据实际的日志存储方式实现
            return {
                "success": True,
                "deleted_count": 0,
                "message": "错误日志清理功能待实现"
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "deleted_count": 0
            }

    def _validate_cleanup_rules(self, rules: Dict[str, Any]) -> Dict[str, Any]:
        """验证清理规则配置"""
        validated_rules = {}
        
        for rule_key, rule_config in rules.items():
            if not isinstance(rule_config, dict):
                raise ValidationError(f"清理规则配置格式错误: {rule_key}")
            
            # 验证必需字段
            if "retention_days" not in rule_config:
                raise ValidationError(f"清理规则缺少retention_days字段: {rule_key}")
            
            retention_days = rule_config["retention_days"]
            if not isinstance(retention_days, int) or retention_days < 1:
                raise ValidationError(f"retention_days必须是大于0的整数: {rule_key}")
            
            # 验证可选字段
            enabled = rule_config.get("enabled", True)
            if not isinstance(enabled, bool):
                raise ValidationError(f"enabled字段必须是布尔值: {rule_key}")
            
            validated_rules[rule_key] = {
                "retention_days": retention_days,
                "enabled": enabled,
                "description": rule_config.get("description", ""),
                "updated_at": datetime.now().isoformat()
            }
        
        return validated_rules

    def _get_default_cleanup_rules(self) -> Dict[str, Any]:
        """获取默认清理规则"""
        return {
            "operation_logs": {
                "retention_days": 90,
                "enabled": True,
                "description": "操作日志保留90天"
            },
            "login_records": {
                "retention_days": 180,
                "enabled": False,
                "description": "登录记录保留180天"
            },
            "deleted_users": {
                "retention_days": 365,
                "enabled": True,
                "description": "已删除用户数据保留365天"
            },
            "temp_files": {
                "retention_days": 7,
                "enabled": True,
                "description": "临时文件保留7天"
            },
            "error_logs": {
                "retention_days": 30,
                "enabled": True,
                "description": "错误日志保留30天"
            }
        }

    def _generate_cleanup_id(self) -> str:
        """生成清理ID"""
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        return f"CL{timestamp}"

    async def _save_cleanup_record(self, cleanup_record: Dict[str, Any]):
        """保存清理记录"""
        try:
            records = self._load_cleanup_records()
            records.append(cleanup_record)
            # 只保留最近100条记录
            if len(records) > 100:
                records = records[-100:]
            self._save_cleanup_records(records)
        except Exception as e:
            logger.error(f"保存清理记录失败: {e}")

    def _load_cleanup_records(self) -> List[Dict[str, Any]]:
        """加载清理记录"""
        try:
            # 从系统配置加载清理记录
            config = self.db.query(SystemConfig).filter(
                SystemConfig.config_key == "cleanup.history_records"
            ).first()
            
            if config and config.config_value:
                return json.loads(config.config_value)
            return []
        except Exception as e:
            logger.error(f"加载清理记录失败: {e}")
            return []

    def _save_cleanup_records(self, records: List[Dict[str, Any]]):
        """保存清理记录"""
        try:
            config = self.db.query(SystemConfig).filter(
                SystemConfig.config_key == "cleanup.history_records"
            ).first()
            
            records_json = json.dumps(records, ensure_ascii=False)
            
            if config:
                config.config_value = records_json
            else:
                config = SystemConfig(
                    config_key="cleanup.history_records",
                    config_value=records_json,
                    config_category="system",
                    config_type="json",
                    display_name="数据清理历史记录",
                    description="数据清理操作的历史记录",
                    group_name="数据清理",
                    created_by="system",
                    updated_by="system"
                )
                self.db.add(config)
            
            self.db.commit()
        except Exception as e:
            logger.error(f"保存清理记录失败: {e}")